package scau.mis4.chanyulin.atm.view;

import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Cursor;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.PasswordField;
import javafx.scene.control.TextField;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import scau.mis4.chanyulin.atm.APP;
import scau.mis4.chanyulin.atm.base.common.CODE;
import scau.mis4.chanyulin.atm.base.utils.RegUtils;
import scau.mis4.chanyulin.atm.domain.Account;
import scau.mis4.chanyulin.atm.domain.Receipt;

/**
 * Created by chanyulin on 2018/4/27.
 * 显示器图形，包含多个显示页面
 */
public class MonitorView extends HBox {

    // 相关控件
    private VBox printer;
    private Label infoLabel;
    private TextField textField;
    private PasswordField passwordField;
    private Button[] btArr;

    public MonitorView() {
        // 初始化按钮
        btArr = new Button[6];
        for (int i = 0; i < btArr.length; i++) {
            Button bt = new Button("");
            bt.setPrefSize(50, 35);
            bt.setFocusTraversable(false);
            bt.setCursor(Cursor.HAND);
            btArr[i] = bt;
        }

        VBox btPanelLeft = new VBox(10);
        VBox btPanelRight = new VBox(10);

        btPanelLeft.getChildren().addAll(btArr[0], btArr[1], btArr[2]);
        btPanelRight.getChildren().addAll(btArr[3], btArr[4], btArr[5]);

        // 初始化屏幕内容
        printer = new VBox();
        infoLabel = new Label();
        textField = new TextField();
        passwordField = new PasswordField();

        printer.setSpacing(15);
        printer.setPrefSize(200, 100);
        printer.setAlignment(Pos.CENTER);
        printer.getChildren().add(infoLabel);
        printer.setPadding(new Insets(0, 10, 0 , 10));

        // 添加所有控件
        this.getChildren().addAll(btPanelLeft, printer, btPanelRight);
        this.setAlignment(Pos.CENTER);

        // 默认跳转到欢迎页面
        this.goToWelcomePage();
    }

    /**
     * 跳转至关机后的空页面
     */
    public void goToEmptyPage() {
        this.clearAllButtonSettings();
        this.changeInfo("");
        this.hideAllInputs();
    }

    /**
     * 跳转至欢迎页面
     */
    public void goToWelcomePage() {
        this.clearAllButtonSettings();
        this.changeInfo("中国农业银行欢迎您！");
        this.hideAllInputs();
    }

    /**
     * 跳转至验证页面
     */
    public void goToAuthorizePage() {

        this.changeInfo("读卡成功，请输入密码");
        this.showPasswordInput();

        // 添加监听器
        this.addEjectCardListener(btArr[2]);
        btArr[5].setText("确认");
        btArr[5].setOnAction(e -> {
            Account account = APP.ATM.getCurrentAccount();
            if (account != null) {
                String password = passwordField.getText();
                if (password.equals(account.getPassword())) {
                    APP.loggerView.log("验证成功，账号：" + account.getCardId() + "；用户姓名：" + account.getName());
                    this.goToServiceSelectPage();
                } else {
                    APP.loggerView.log("验证失败，账号：" + account.getCardId());
                    this.changeInfo("密码错误，请重新输入密码");
                    passwordField.clear();
                }
            } else {
                // 异常
                this.goToErrorPage(CODE.ERR_SESSION_EMPTY);
            }
        });

    }

    /**
     * 跳转至功能选择页面
     */
    public void goToServiceSelectPage() {

        this.hideAllInputs();
        this.clearAllButtonSettings();
        this.changeInfo("请选择服务");

        // 添加监听器
        btArr[1].setText("查询");
        btArr[1].setOnAction(e -> {
            goToCheckAccountPage();
        });
        this.addEjectCardListener(btArr[2]);
        btArr[4].setText("存款");
        btArr[4].setOnAction(e -> {
            goToPutMoneyPage();
        });
        btArr[5].setText("取款");
        btArr[5].setOnAction(e -> {
            goToWithdrawPage();
        });

    }

    /**
     * 跳转至账户信息查询页面
     */
    public void goToCheckAccountPage() {

        APP.loggerView.log("用户进入账户信息查询页面");

        clearAllButtonSettings();

        // 添加监听器
        this.addToServiceSelectPageListener(btArr[5]);
        this.addEjectCardListener(btArr[2]);

        Account currentAccount = APP.ATM.getCurrentAccount();
        if (null != currentAccount) {
            this.changeInfo(
                "卡号：" + currentAccount.getCardId() + "\n" +
                "用户：" + currentAccount.getName() + "\n" +
                "余额：" + currentAccount.getBalance()
            );
        } else
            this.goToErrorPage(CODE.ERR_SESSION_EMPTY);
    }

    /**
     * 跳转至取款页面
     */
    public void goToWithdrawPage() {

        APP.loggerView.log("用户进入取款服务");

        this.clearAllButtonSettings();
        this.showTextInput();
        this.changeInfo("请选择或输入取款金额");

        // 添加监听器
        this.addToServiceSelectPageListener(btArr[2]);

        this.addTextBindInputListener(btArr[0], "100");
        this.addTextBindInputListener(btArr[1], "200");
        this.addTextBindInputListener(btArr[3], "500");
        this.addTextBindInputListener(btArr[4], "1000");

        btArr[5].setText("确认");
        btArr[5].setOnAction(e -> {
            String text = textField.getText();
            // 取款金额校验，必须为正整数且为100的倍数
            if (RegUtils.isPositiveInteger(text) && Integer.valueOf(text) % 100 == 0) {
                int moneyNeed = Integer.valueOf(text);
                APP.loggerView.log("用户输入取款金额有效");

                int resultCode = APP.ATM.withdrawMoneyHandler(moneyNeed);
                if (CODE.MSG_SUCCESS == resultCode) {
                    int moneyEjected = moneyNeed;
                    // 回调方法
                    APP.cashierView.ejectMoneySuccessCallBack();
                    this.goToMoneyEjectedPage(moneyEjected);
                } else
                    this.goToErrorPage(resultCode);
            } else {
                APP.loggerView.log("用户输入取款金额有误：" + textField.getText());
                this.changeInfo("请输入正确的取款金额");
                textField.clear();
            }
        });

    }

    /**
     * 跳转至取钱页面
     */
    public void goToMoneyEjectedPage(int moneyEjected) {

        this.clearAllButtonSettings();
        this.hideTextInput();
        this.changeInfo("已出钞，请及时取走钞票");
        APP.loggerView.log("取款成功，取款金额：" + moneyEjected);

        this.addEjectCardListener(btArr[1]);
        this.addToServiceSelectPageListener(btArr[2]);
        this.addPrintReceiptListener(btArr[5], moneyEjected);

    }

    /**
     * 跳转至存款页面
     */
    public void goToPutMoneyPage() {

        APP.loggerView.log("用户进入存款服务");

        this.clearAllButtonSettings();
        this.hideTextInput();
        this.changeInfo("请往出钞机放入钞票");

        // 添加监听器
        this.addToServiceSelectPageListener(btArr[2]);
        btArr[5].setText("确认");
        btArr[5].setOnAction(e -> {
            goToSaveMoneyCheckPage();
        });

    }

    /**
     * 跳转至存款钞票清点确认页面
     */
    public void goToSaveMoneyCheckPage() {

        clearAllButtonSettings();
        hideAllInputs();

        btArr[2].setText("返回");
        btArr[2].setOnAction(e -> {
            APP.loggerView.log("用户请求重新放入钞票");
            int resultCode = APP.ATM.ejectMoneyCacheHandler();
            if (CODE.MSG_SUCCESS == resultCode) {
                this.goToPutMoneyPage();
                APP.cashierView.ejectMoneySuccessCallBack();
                APP.loggerView.log("出钞成功");
            } else
                goToErrorPage(resultCode);
        });

        btArr[5].setText("确认");
        btArr[5].setDisable(true);
        int resultCode = APP.ATM.moveMoneyToCacheHandler();
        if (CODE.MSG_SUCCESS == resultCode) {
            int moneyCounted = APP.ATM.countMoneyHandler();
            APP.loggerView.log("用户一共放入钞票" + moneyCounted + "元");
            if (moneyCounted > 0) {
                btArr[5].setDisable(false);
                APP.cashierView.countMoneySuccessCallBack();
                changeInfo("一共放入钞票" + moneyCounted + "元，请确认");
                btArr[5].setOnAction(e1 -> {
                    int resultCode1 = APP.ATM.saveMoneyHandler();
                    if (CODE.MSG_SUCCESS == resultCode1) {
                        this.goToSaveMoneyFinishedPage(moneyCounted);
                    } else
                        this.goToErrorPage(resultCode1);
                });
            } else
                this.goToErrorPage(CODE.ERR_NUMBER_OUT_OF_RANGE);
        } else
            this.goToErrorPage(resultCode);

    }

    /**
     * 跳转至存款成功页面
     */
    public void goToSaveMoneyFinishedPage(int moneyCounted) {
        this.clearAllButtonSettings();

        this.changeInfo("存款成功");
        APP.loggerView.log("存款成功，存款金额：" + moneyCounted);

        this.addEjectCardListener(btArr[1]);
        this.addToServiceSelectPageListener(btArr[2]);
        this.addPrintReceiptListener(btArr[5], 0 - moneyCounted);
    }

    /**
     * 跳转至异常页面
     */
    public void goToErrorPage(int errorCode) {

        this.clearAllButtonSettings();
        this.hideAllInputs();

        switch (errorCode) {
            case CODE.ERR_BALANCE_DEFICIENCY :
                APP.loggerView.log("账户余额不足");
                this.changeInfo("您的账户余额不足");
                break;
            case CODE.ERR_OUT_OF_CASH :
                APP.loggerView.log("出钞机钞票不足");
                this.changeInfo("出钞机钞票不足");
                break;
            default :
                APP.loggerView.log("系统出现异常，代号：" + errorCode);
                this.changeInfo("异常代号：" + errorCode + "，请联系工作人员");
                break;
        }

        this.addToServiceSelectPageListener(btArr[5]);
        this.addEjectCardListener(btArr[2]);

    }

    /**
     * 为按钮添加退卡的监听器
     * @param target
     */
    private void addEjectCardListener(Button target) {
        target.setText("退卡");
        target.setOnAction(e -> {
            int resultCode = APP.ATM.ejectCardHandler();
            if (CODE.MSG_SUCCESS == resultCode) {
                APP.cardReaderView.ejectCardSuccessCallBack();
                this.goToWelcomePage();
                APP.loggerView.log("用户退卡成功");
            } else {
                this.goToErrorPage(resultCode);
            }
        });
    }

    /**
     * 为按钮添加打印取款凭条的监听器
     * @param target
     */
    private void addPrintReceiptListener(Button target, int money) {
        target.setText("打印");
        target.setOnAction(e1 -> {
            Receipt receipt = new Receipt(APP.ATM.getCurrentAccount(), money);
            int resultCode = APP.ATM.printReceiptHandler(receipt);
            if (CODE.MSG_SUCCESS == resultCode) {
                this.changeInfo("凭条打印成功");
                APP.loggerView.log("凭条打印成功");
                // 执行回调方法
                APP.receiptPrinterView.printReceiptSuccessCallBack();
                target.setDisable(true);
            } else {
                this.changeInfo("凭条打印失败");
                APP.loggerView.log("凭条打印失败");
            }
        });
    }

    /**
     * 为按钮添加返回到服务选择页面的监听器
     * @param target
     */
    private void addToServiceSelectPageListener(Button target) {
        target.setText("返回");
        target.setOnAction(e -> {
            this.goToServiceSelectPage();
        });
    }

    /**
     * 按钮文本绑定输入文本
     * @param target
     * @param bindText
     */
    private void addTextBindInputListener(Button target, String bindText) {
        target.setText(bindText);
        target.setOnAction(e -> {
            textField.setText(bindText);
        });
    }

    /**
     * 显示文本输入框
     */
    private void showTextInput() {
        textField.clear();
        printer.getChildren().add(textField);
    }

    /**
     * 隐藏文本输入框
     */
    private void hideTextInput() {
        printer.getChildren().remove(textField);
    }

    /**
     * 显示密码输入框
     */
    private void showPasswordInput() {
        passwordField.clear();
        printer.getChildren().add(passwordField);
    }

    /**
     * 隐藏密码输入框
     */
    private void hidePasswordInput() {
        printer.getChildren().remove(passwordField);
    }

    /**
     * 隐藏所有输入框
     */
    private void hideAllInputs() {
        printer.getChildren().remove(textField);
        printer.getChildren().remove(passwordField);
    }

    /**
     * 清空所有按钮的属性
     */
    private void clearAllButtonSettings() {
        for (Button bt : btArr) {
            bt.setText("");
            bt.setDisable(false);
            bt.setOnAction(null);
        }
    }

    /**
     * 修改屏幕显示内容
     * @param info
     */
    public void changeInfo(String info) {
        infoLabel.setText(info);
    }

}
